package MainClasses.FromAPCompSci;

import java.util.*;

public class MySet<E>
{
    private ListNode list;

    public int size()
    {
        int size = 0;
        ListNode temp = list;
        while(temp != null)
        {
            size++;
            temp = temp.getNext();
        }
        return size;
    }
    
    public boolean contains(Object obj)
    {
        ListNode temp = list;
        while(temp != null)
        {
            if(obj.equals(temp.getValue()))
            {
                return true;
            }
            temp = temp.getNext();
        }
        return false;
    }

    // if obj is not present in this set, adds obj and
    // returns true; otherwise returns false
    public boolean add(E obj)
    {
        if(contains(obj))
        {
            return false;
        }
        list = new ListNode(obj, list);
        return true;
    }

    // if obj is present in this set, removes obj and
    // returns true; otherwise returns false
    public boolean remove(Object obj)
    {
        ListNode temp = list;
        ListNode onebefore = null;
        while(temp != null)
        {
            if(obj.equals(temp.getValue()))
            {
                if(onebefore == null)
                {
                    list = list.getNext();
                    return true;
                }
                onebefore.setNext(temp.getNext());
                return true;
            }
            onebefore = temp;
            temp = temp.getNext();
            
        }
        return false;
    }

    public Iterator<E> iterator()
    {
        return new MySetIterator<E>();
    }

    @Override
    public String toString()
    {
        ListNode temp = list;
        String s = "";
        while (temp != null)
        {
            s += temp.getValue() + " ";
            temp = temp.getNext();
        }
        return s;
    }

    private class MySetIterator<E> implements Iterator<E>
    {
        private ListNode twoBefore;
        private ListNode oneBefore;
        private ListNode next;

        public MySetIterator()
        {
            twoBefore = null;
            oneBefore = null;
            next = list;
        }

        public boolean hasNext()
        {
            return next != null;
        }

        public E next()
        {
            twoBefore = oneBefore;
            oneBefore = next;
            next = next.getNext();
            return (E)oneBefore.getValue();
        }

        // removes the last element that was returned by next
        public void remove()
        {
            if (twoBefore == null)
            {
                list = list.getNext();
                oneBefore = null;
            }
            else
            {
                twoBefore.setNext(next);
                oneBefore = twoBefore;
                twoBefore = null;
            }
        }
    }
}